<?php

declare(strict_types=1);

namespace RX\Core;

use RX\Enums\CommonEnum;
use RX\Exception\BizException;
use RX\Helpers\StringHelper;

/**
 * Class Enum
 * @package RX\Core\CoreEnum
 * @method getMessage($code)
 */
abstract class CoreEnum
{
    public function __call($name, $arguments)
    {
        if (!StringHelper::startsWith($name, 'get')) {
            throw new BizException(CommonEnum::class, CommonEnum::INVALID_PARAMS, 'The function is not defined!');
        }
        if (!isset($arguments) || count($arguments) === 0) {
            throw new BizException(CommonEnum::class, CommonEnum::INVALID_PARAMS, 'The Code is required');
        }

        $code = $arguments[0];
        $name = strtolower(substr($name, 3));
        if (isset($this->$name)) {
            return isset($this->$name[$code]) ? $this->$name[$code] : '';
        }

        // 获取常量
        $ref       = new \ReflectionClass(static::class);
        $constants = $ref->getConstants();

        $arr = $this->getAnnotationsByName($name, $constants);
        if (version_compare(PHP_VERSION, "7", '<')) {
            // 版本小于7
            return isset($arr[$code]) ? $arr[$code] : '';
        }

        $this->$name = $arr;
        return isset($this->$name[$code]) ? $this->$name[$code] : '';
    }

    public static function __callStatic($method, $arguments)
    {
        return static::getInstance()->$method(...$arguments);
    }

    protected function getAnnotationsByName($name, $properties)
    {
        $result = [];
        foreach ($properties as $key => $val) {
            $ret          = new \ReflectionClassConstant(static::class, $key);
            $result[$val] = $this->getCommentByName($ret->getDocComment(), $name);
        }
        return $result;
    }

    /**
     * @desc   根据name解析doc获取对应注释
     * @param string $doc 注释
     * @param string $name 字段名
     * @return mixed|null
     */
    protected function getCommentByName($doc, $name)
    {
        $name    = StringHelper::studly($name);
        $pattern = "/\@{$name}\(\"(.*)\"\)/U";
        if (preg_match($pattern, $doc, $result)) {
            if (isset($result[1])) {
                return $result[1];
            }
        }
        return null;
    }
}
